/**
 * 项目模板复制模块
 * 
 * 用于复制和处理 Flutter 项目的 lib 目录文件
 * 支持从Git仓库获取代码
 * 支持创建packages目录并克隆常用库
 */

import fsExtra from 'fs-extra'
const { mkdtempSync, existsSync, removeSync, readFileSync, writeFileSync, ensureDirSync, copySync, readdirSync, statSync } = fsExtra;
import { join } from 'path';
import { tmpdir } from 'os';
import { exec } from 'child_process';
import { printColored } from './utils.js';


/**
 * 从Git仓库克隆代码到临时目录
 * 
 * @param {string} gitUrl - Git仓库URL
 * @param {string} branch - 分支名称
 * @returns {Promise<string|null>} 临时目录路径或null
 */
async function cloneGitRepo (gitUrl, branch = 'master') {
  return new Promise((resolve) => {
    try {
      // 创建临时目录
      const tempDir = mkdtempSync(join(tmpdir(), 'flutter-cli-'));
      printColored(`正在从Git仓库克隆代码到临时目录: ${tempDir}`, 'blue');

      // 克隆指定分支的代码
      const command = `git clone -b ${branch} --single-branch ${gitUrl} "${tempDir}"`;

      exec(command, (error, stdout, stderr) => {
        if (error) {
          printColored(`Git仓库克隆失败: ${error.message}`, 'red');
          if (existsSync(tempDir)) {
            removeSync(tempDir);
          }
          resolve(null);
          return;
        }

        printColored("Git仓库克隆成功！", 'green');
        resolve(tempDir);
      });
    } catch (e) {
      printColored(`创建临时目录失败: ${e.message}`, 'red');
      resolve(null);
    }
  });
}

/**
 * 复制并处理lib目录文件和pubspec.yaml
 * 支持从本地目录或Git仓库复制
 * 
 * @param {string} sourceDir - 源目录路径
 * @param {string} targetDir - 目标目录路径
 * @param {string} projectName - 项目名称 
 * @param {string} projectType - 项目类型 ('app'或'module')
 * @param {string} templateType - 模板类型 ('only','min','normal','pro')
 * @param {string} packageName - 包名
 * @param {string} branch - Git分支
 * @param {string} gitUrl - Git仓库URL
 * @returns {Promise<boolean>} 是否复制成功
 */
export async function copyLibDirectory (
  sourceDir,
  targetDir,
  projectName,
  projectType,
  templateType,
  packageName,
  branch = 'master',
  gitUrl = 'https://gitee.com/tengteng_fan/hzy_basic_project.git',
) {
  try {
    // 如果提供了gitUrl，从Git仓库获取代码
    let tempDir = null;
    if (gitUrl) {
      tempDir = await cloneGitRepo(gitUrl, branch);
      if (!tempDir) {
        return false;
      }
      sourceDir = tempDir;
    }
    try {
      // 复制pubspec.yaml
      // 源目录路径拼接pubspec.yaml文件名
      const pubspecSource = join(sourceDir, 'pubspec.yaml');
      // 目标目录路径拼接pubspec.yaml文件名
      const pubspecTarget = join(targetDir, 'pubspec.yaml');
      // 确保目标目录存在
      if (existsSync(pubspecSource)) {
        printColored("正在复制并处理pubspec.yaml...", 'blue');

        // 读取源文件内容
        let sourceContent = readFileSync(pubspecSource, 'utf8');

        // 提取dependencies部分
        let dependenciesContent = 'dependencies:\n';
        const dependenciesRegex = /dependencies:[\s\S]*?(?=\n\s*dev_dependencies:)/;
        const dependenciesMatch = sourceContent.match(dependenciesRegex);
        if (dependenciesMatch) {
          dependenciesContent = dependenciesMatch[0];
        }

        // 提取assets部分
        let assetsContent = '';
        let assetsRegex = '';
        if (projectType == 'app') {
          assetsRegex = /  uses-material-design: true[\s\S]*/;
        } else if (projectType == 'module') {
          assetsRegex = /  uses-material-design: true[\s\S]*?(?=\n\s*module:)/;
        }
        const assetsMatch = sourceContent.match(/  uses-material-design: true[\s\S]*/);
        if (assetsMatch) {
          printColored("正在提取assets部分...", 'blue');
          printColored("assetsMatch[0]: " + assetsMatch, 'blue');
          assetsContent = assetsMatch[0];
        }

        // 读取目标文件内容
        let targetContent = '';
        if (existsSync(pubspecTarget)) {
          targetContent = readFileSync(pubspecTarget, 'utf8');
        }

        // 替换项目名称和描述
        targetContent = targetContent.replace(
          /description:\s*["'].*?["']/g,
          'description: "火之夜工作室 Flutter 脚手架"'
        );

        // 添加publish_to配置防止意外发布
        if (!targetContent.includes('publish_to:')) {
          targetContent = targetContent.replace(
            `name: ${projectName}\n`,
            `name: ${projectName}\npublish_to: none\n`
          );
        }

        // 替换dependencies部分
        if (targetContent.match(dependenciesRegex)) {
          targetContent = targetContent.replace(dependenciesRegex, dependenciesContent);
        } else {
          // 如果没有找到dependencies部分，添加到文件末尾
          targetContent += '\n' + dependenciesContent;
        }
        if (targetContent.match(assetsRegex)) {
          targetContent = targetContent.replace(assetsRegex, assetsContent);
        } else {
          // 如果没有找到assets部分，添加到文件末尾
          targetContent += '\n' + assetsContent;
        }

        // 写入目标文件
        writeFileSync(pubspecTarget, targetContent, 'utf8');
      }

      // 复制lib目录
      const libSource = join(sourceDir, 'lib');
      const libTarget = join(targetDir, 'lib');

      if (existsSync(libSource)) {
        printColored("正在复制lib目录...", 'blue');

        // 确保目标lib目录存在
        ensureDirSync(libTarget);

        // 复制lib目录内容
        copySync(libSource, libTarget, {
          overwrite: true,
          filter: (src) => {
            // 可以在这里添加过滤逻辑，例如排除某些文件
            return true;
          }
        });
      }

      // 复制assets目录（如果存在）
      const assetsSource = join(sourceDir, 'assets');
      const assetsTarget = join(targetDir, 'assets');
      if (existsSync(assetsSource)) {
        printColored("正在复制assets目录...", 'blue');
        copySync(assetsSource, assetsTarget, { overwrite: true });
      }
      // 复制test目录 (如果存在)
      const testSource = join(sourceDir, 'test');
      const testTarget = join(targetDir, 'test');
      if (existsSync(testSource)) {
        printColored("正在复制test目录...", 'blue');
        copySync(testSource, testTarget, { overwrite: true });
      }
      // 全局替换包名和项目名称
      processLibFiles(libTarget, packageName, projectName);
      printColored("正在处理替换lib文件项目名称...", 'blue');
      processLibFiles(testTarget, packageName, projectName);
      printColored("正在处理test目录文件项目名称...", 'blue');
      printColored("项目模板复制完成！", 'green');
      return true;
    } finally {
      // 清理临时目录
      if (tempDir && existsSync(tempDir)) {
        removeSync(tempDir);
      }
    }
  } catch (e) {
    printColored(`复制项目模板时发生错误: ${e.message}`, 'red');
    return false;
  }
}


/**
 * 复制vscode配置文件
 * 
 * @param {string} targetDir - 目标目录路径
 */
export async function copyVscode (targetDir) {

  /**
   * 第一步:创建.vscode 文件夹.
   * - 配置.vscode 文件夹的路径.
   * 
   * - 如果.vscode 目录存在，先删除
   * - 重新创建 .vscode 目录
   * 第二步: 克隆 vscode_config 仓库代码到.vscode 目录
   * - 从https://gitee.com/tengteng_fan/vscode_config.git仓库克隆代码到临时目录,
   * - 获取临时文件夹中的flutter_vscode文件夹里面的文件
   * - 复制到 .vscode 目录中.
   */

  // 定义.vscode 目录路径
  const vscodeDir = join(targetDir, '.vscode')

  if (existsSync(vscodeDir)) {
    printColored("删除已存在的.vscode目录...", 'blue');
    removeSync(vscodeDir);
  }
  printColored("创建.vscode目录...", 'blue');
  ensureDirSync(vscodeDir);
  printColored("克隆vscode_config仓库代码到.vscode目录...", 'blue');

  const vscodeConfigRepoUrl = 'https://gitee.com/tengteng_fan/vscode_config.git';
  // 配置 vscode_config 临时文件夹
  const tempDir = await cloneGitRepo(vscodeConfigRepoUrl);
  printColored("vscode_config 仓库代码克隆完成...", 'blue');
  // 打印临时目录路径
  printColored(`临时目录路径: ${tempDir}`, 'blue');
  // 定义 vscode_config 目录路径
  const vscodeConfigDir = join(tempDir, 'flutter_vscode');
  // 打印 vscode_config 目录路径
  printColored(`vscode_config 目录路径: ${vscodeConfigDir}`, 'blue');
  // 复制 vscode_config 目录内容到 .vscode 目录
  copySync(vscodeConfigDir, vscodeDir, { overwrite: true });

  // 清理临时目录
  if (tempDir && existsSync(tempDir)) {
    removeSync(tempDir);
  }
}

export async function copyPackages (targetDir) {
  /**
    * 待定: 暂时使用本地packages目录,里面的内容通过git clone 下载在package文件里.
    * 后续会增加功能选项.根据用户选择使用本地packages目录,
    * 还是直接在pubspec.yaml中添加依赖.
   */

  // 创建packages目录
  const packagesDir = join(targetDir, 'packages');

  // 如果packages目录存在，先删除
  if (existsSync(packagesDir)) {
    printColored("删除已存在的packages目录...", 'blue');
    removeSync(packagesDir);
  }

  // 重新创建packages目录
  printColored("创建packages目录...", 'blue');
  ensureDirSync(packagesDir);

  // 克隆常用库到packages目录
  printColored("正在克隆常用库到packages目录...", 'blue');



  // 并行克隆两个仓库
  const toolRepoUrl = 'https://gitee.com/hot_night/hzy_normal_tool.git';
  const networkRepoUrl = 'https://gitee.com/hot_night/hzy_normal_network.git';
  let proArr = [];
  if (templateType === '0') {
    proArr = [
      cloneRepo(toolRepoUrl, join(packagesDir, 'hzy_normal_tool'), 'hzy_normal_tool'),
    ];
  } else {
    proArr = [
      cloneRepo(toolRepoUrl, join(packagesDir, 'hzy_normal_tool'), 'hzy_normal_tool'),
      cloneRepo(networkRepoUrl, join(packagesDir, 'hzy_normal_network'), 'hzy_normal_network')
    ];
  }
  // 等待两个仓库克隆完成
  await Promise.all(proArr);



  printColored("packages目录克隆完成！", 'green');
}

// 定义克隆仓库的Promise函数
const cloneRepo = (repoUrl, targetDir, repoName) => {
  return new Promise((resolve) => {
    const command = `git clone ${repoUrl} "${targetDir}"`;
    exec(command, (error, stdout, stderr) => {
      if (error) {
        printColored(`克隆${repoName}库失败: ${error.message}`, 'yellow');
        resolve(false);
      } else {
        printColored(`克隆${repoName}库成功！`, 'green');
        resolve(true);
      }
    });
  });
};


/**
 * 处理lib目录中的文件，替换包名等
 * 
 * @param {string} libDir - lib目录路径
 * @param {string} packageName - 包名
 */
function processLibFiles (targetDir, packageName, projectName) {
  try {
    // 递归处理目录中的所有文件
    const processDir = (dir) => {
      const files = readdirSync(dir);

      for (const file of files) {
        const filePath = join(dir, file);
        const stat = statSync(filePath);

        if (stat.isDirectory()) {
          // 递归处理子目录
          processDir(filePath);
        } else if (stat.isFile() && (file.endsWith('.dart') || file.endsWith('.yaml'))) {
          // 处理dart和yaml文件
          let content = readFileSync(filePath, 'utf8');

          // 替换packageName和projectName
          content = content.replace(/hzy_basic_project/g, projectName);
          // 替换包名
          content = content.replace(/com\.example\.hzy_basic_project/g, packageName);

          // 写回文件
          writeFileSync(filePath, content, 'utf8');
        }
      }
    };

    processDir(targetDir);
  } catch (e) {
    printColored(`处理lib文件时发生错误: ${e.message}`, 'yellow');
  }
}

